---
title: CheckAccess
summary: Evaluates the caller's source address against the local-request and IP-allow-list rules; the access-control primitive used by every gated operation.
status: draft
owner: "Not determined from source"
last_reviewed: 2026-09-22
---

# CheckAccess (OP-19)

## Request and response

| Part | Type | Description |
| --- | --- | --- |
| *(none)* | — | This operation takes no parameters. |

| Part | Type | Description |
| --- | --- | --- |
| `<return>` | `HasAccessResponse` | Public fields `HasAccess` (`Boolean`), `Local` (`Boolean`), `EnvironmentApi` (`Boolean`), `RemoteAddress` (`String`). |

## WebMethod attributes

`<WebMethod()>` — bare, no arguments supplied.

## Steps

1. Initialize `HasAccess = False`, `Local = False`, `EnvironmentApi = False`.
2. Set `RemoteAddress = GetIncomingIp()`, which reads the `HTTP_X_FORWARDED_FOR` server variable, falling back to `REMOTE_ADDR` only when that header is null or empty ([BR-04](../business-rules.md#br-04-the-caller's-source-address-prefers-the-forwarded-for-header)) — spoofable, with no trusted-proxy validation (SEC-03, HIGH — see [Authentication and authorization](../authentication-authorization.md)).
3. If `HttpContext.Current.Request.IsLocal`, set `HasAccess = True`, `Local = True` ([BR-02](../business-rules.md#br-02-a-local-request-is-always-approved)) — an unconditional local-request bypass (SEC-11).
4. Call `GetAllowedIPs()`: constructs `New WebEnvironmentService("aduserservices")`, reads the `aduserservices.allowedips` configuration setting, and splits it on `","` into a list. There is no null/empty guard (TD-12, MEDIUM — a missing or unreachable setting propagates as an exception; see [Tech debt](../tech-debt.md) and [Configuration](../configuration.md)).
5. For each entry in the allow-list, call `GetIncomingIp()` again — re-reading the incoming IP rather than reusing the value already computed for `RemoteAddress` (TD-09, LOW inefficiency; see [Tech debt](../tech-debt.md)) — and compare for exact, case-sensitive string equality. On a match, set `HasAccess = True`, `EnvironmentApi = True` ([BR-03](../business-rules.md#br-03-an-allow-listed-source-address-is-approved)).
6. Return the `HasAccessResponse`.

## Process flow

```mermaid
flowchart TD
    A["Call CheckAccess"] --> B["Init HasAccess/Local/<br>EnvironmentApi = False"]
    B --> C["RemoteAddress =<br>GetIncomingIp"]
    C --> D{"Request.IsLocal?"}
    D -->|"Yes"| E["HasAccess = True<br>Local = True"]
    D -->|"No"| F["GetAllowedIPs<br>from configuration"]
    E --> F
    F --> G["For each allow-list entry"]
    G --> H{"entry = GetIncomingIp<br>re-read, exact match?"}
    H -->|"Yes"| I["HasAccess = True<br>EnvironmentApi = True"]
    H -->|"No"| G
    I --> J["Return HasAccessResponse"]
    G -->|"loop done"| J
```

## Shared state effects

None — this operation touches no process-wide state. `HasAccessResponse` fields are local return values constructed per request, not shared state.

## Error handling

This operation has **no `Try`/`Catch` anywhere in its body**. If the environment service is unavailable or `aduserservices.allowedips` is missing, the resulting exception propagates as a framework SOAP fault — whether `CheckAccess` is invoked directly as this operation, or indirectly via H4 from within any of the eight gated operations that call it first. See [Faults](../faults.md) for the service-wide fault model.

## Authorization

This operation has none — because it **is** the access-control primitive that every gated operation calls first. It is itself published and unauthenticated, making it an oracle a caller can use to probe the allow-list (SEC-04, MEDIUM). See [Authentication and authorization](../authentication-authorization.md#sec-svc-005-checkaccess-itself-is-published-and-unauthenticated) for the full mechanism description; this page documents only `CheckAccess`'s own steps.

## Related documentation
- [Service index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Activation and hosting](../activation-hosting.md)
- [Operations](../operations.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Authentication and authorization](../authentication-authorization.md)
- [Configuration](../configuration.md)
- [Dependencies](../dependencies.md)
- [Faults](../faults.md)
- [Operational runbook](../operational-runbook.md)
- [Tech debt](../tech-debt.md)

## Sources
- `src\ADUserServices\clsADUserServices.asmx.vb` (lines 752-796)
